﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Compression.ImageCompressor;
using System.IO;

namespace Compression
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
        Bitmap img = null;
        Bitmap[] tiles = null;
        int k = 0;
        int w = 0;
        int h = 0;

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "Изображения (*.bmp)|*.bmp";
            DialogResult res = dialog.ShowDialog();
            
            if (res == DialogResult.OK || res == DialogResult.Yes)
            {
                img = (Bitmap)Bitmap.FromFile(dialog.FileName);                
            }
            if (img != null)
            {
                //pictureBox1.Image = img;
                //pictureBox1.Width = img.Width;
                //pictureBox1.Height = img.Height;
            }
        }

        private void Allocator(ref float[][] a, int size)
        {
            a = new float[size][];
            for (int i = 0; i < size; i++)
            {
                a[i] = new float[size];
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            int size = (int)blockSize.Value;
            /*if (img != null)
            {
                w = img.Width;
                h = img.Height;
                PreProcessing.Tiling(ref img, size,out tiles);
            }
            else return;*/
            if (originalImage.Image == null) return;


            float[][] A = null;
            Allocator(ref A, size);
            float[][] B = null;
            Allocator(ref B, size);
            float[][] C = null;
            Allocator(ref C, size);

            float[][] AA = null;
            Allocator(ref AA, size);
            float[][] BB = null;
            Allocator(ref BB, size);
            float[][] CC = null;
            Allocator(ref CC, size);

            int QuantVal = (int)quantification.Value;
            int deep = (int)depth.Value;

            #warning Имя файла
            string filename = "ResBitmap.wwt"; //!!!

            ImageHeader header = new ImageHeader();
            header.BlockSize = (ushort)size;
            header.ColorICT = ictColorMode.Checked;
            header.Deep = (ushort)deep;
            header.Height = (ushort)originalImage.Image.Height;
            header.Width = (ushort)originalImage.Image.Width;
            header.Offset = valuesOffset.Checked;
            header.Quantilization = (ushort)QuantVal;

            FileWorker worker = new FileWorker(filename, false);
            header.SaveHeader(worker);

            int rows;
            int cols;
            int all;
            PreProcessing.GetCountTiles(originalImage.Image, size, out rows, out cols, out all);
            for (int i=0;i<all;i++){
                PreProcessing.GetTile((Bitmap)originalImage.Image, size, i, ref AA, ref BB, ref CC);
                if (header.ColorICT)
                {
                    PreProcessing.ICT(ref AA, ref BB, ref CC, ref A, ref B, ref C);
                }
                else
                {
                    PreProcessing.YUV(ref AA, ref BB, ref CC, ref A, ref B, ref C);
                }

                if (header.Offset)
                {
                    PreProcessing.Offset(ref A, size, size, false);
                    PreProcessing.Offset(ref B, size, size, false);
                    PreProcessing.Offset(ref C, size, size, false);
                }

                for (int j = 0; j < deep+1; j++)
                {
                    ImagePacker.Transform(ref A, ref AA, size>>j);
                    ImagePacker.Transform(ref B, ref BB, size>>j);
                    ImagePacker.Transform(ref C, ref CC, size>>j);
                    PreProcessing.Move(ref AA, ref A, size>>j);
                    PreProcessing.Move(ref BB, ref B, size>>j);
                    PreProcessing.Move(ref CC, ref C, size>>j);
                }

                PreProcessing.Quantilization(ref A, size, size, QuantVal, true);
                PreProcessing.Quantilization(ref B, size, size, QuantVal, true);
                PreProcessing.Quantilization(ref C, size, size, QuantVal, true);

                PreProcessing.SavePackets(size, A, B, C, worker);
                               
            }            
            worker.Dispose();
            MessageBox.Show("Complete");
        }

        

        private void button3_Click(object sender, EventArgs e)
        {
            ImageHeader header = new ImageHeader();
            header.Deep = 3;
            header.BlockSize = 256;
            header.ColorICT = false;
            header.Height = 2250;// (short)img.Height;
            header.Width = 4500;// (short)img.Width;
            header.Quantilization = 8;
            header.Offset = true;   

            string filename="output.wwt";
            FileWorker worker = new FileWorker(filename, false);

            header.SaveHeader(worker);
            worker.Dispose();

            worker = new FileWorker(filename, true);
            ImageHeader header2 = new ImageHeader();
            header2.LoadHeader(worker);
            worker.Dispose();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            /*ImagePacket pak = new ImagePacket();

            pak.FirstCollection.Add(new WaveletPoint(1, 1, 4));
            pak.SecondCollection.Add(new WaveletPoint(5, 7, 2));
            pak.ThridCollection.Add(new WaveletPoint(10, 20, 30));

            ImagePacket pak2 = null;
            object temp = null;
            string res = Serializer.Serialize(pak);
            Serializer.Deserialize(res, out temp);
            pak2 = (ImagePacket)temp;*/
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            originalImage.Image = new Bitmap(originalImage.Width, originalImage.Height);
            compressedImage.Image = new Bitmap(compressedImage.Width, compressedImage.Height);
        }

        private void loadImageButton_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "Bitmap Images (*.bmp)|*.bmp|Wavelet Images (*.wwt)|*.wwt";
            DialogResult res = dialog.ShowDialog();

            if (res == DialogResult.OK || res == DialogResult.Yes)
            {
                if (dialog.FileName.Contains(".bmp")){
                    img = (Bitmap)Bitmap.FromFile(dialog.FileName);
                    if (img != null)
                    {
                        originalImage.Image = img;
                        originalImage.Width = img.Width;
                        originalImage.Height = img.Height;
                    }
                }else{
                    LoadWwtImage(dialog.FileName);
                }
            }
            
        }

        private void LoadWwtImage(string filename)
        {
            FileWorker worker = new FileWorker(filename,true);
            ImageHeader header = new ImageHeader();
            try
            {
                header.LoadHeader(worker);
            }
            catch (Exception)
            {
                return;
            }

            float[][] A = null;
            Allocator(ref A, header.BlockSize);
            float[][] B = null;
            Allocator(ref B, header.BlockSize);
            float[][] C = null;
            Allocator(ref C, header.BlockSize);

            float[][] AA = null;
            Allocator(ref AA, header.BlockSize);
            float[][] BB = null;
            Allocator(ref BB, header.BlockSize);
            float[][] CC = null;
            Allocator(ref CC, header.BlockSize);

            Bitmap res = new Bitmap(header.Width, header.Height);
            int rows;
            int cols;
            int all;
            PreProcessing.GetCountTiles(res, header.BlockSize, out rows, out cols, out all);

            for (int i = 0; i < all; i++)
            {
                
                ImagePacket pack = new ImagePacket();
                pack.LoadPacket(worker);
                
                PreProcessing.LoadMatrixFromPacket(pack,ref A,ref B,ref C,header.BlockSize);

                PreProcessing.Quantilization(ref A, header.BlockSize, header.BlockSize, header.Quantilization, false);
                PreProcessing.Quantilization(ref B, header.BlockSize, header.BlockSize, header.Quantilization, false);
                PreProcessing.Quantilization(ref C, header.BlockSize, header.BlockSize, header.Quantilization, false);

                for (int j = header.Deep-1; j >= 0; j--)
                {
                    ImagePacker.Syntes(ref A, ref AA, header.BlockSize >> j);
                    ImagePacker.Syntes(ref B, ref BB, header.BlockSize >> j);
                    ImagePacker.Syntes(ref C, ref CC, header.BlockSize >> j);
                    PreProcessing.Move(ref AA, ref A, header.BlockSize >> j);
                    PreProcessing.Move(ref BB, ref B, header.BlockSize >> j);
                    PreProcessing.Move(ref CC, ref C, header.BlockSize >> j);
                }
                //k = 0;

                if (header.Offset)
                {
                    PreProcessing.Offset(ref A, header.BlockSize, header.BlockSize, true);
                    PreProcessing.Offset(ref B, header.BlockSize, header.BlockSize, true);
                    PreProcessing.Offset(ref C, header.BlockSize, header.BlockSize, true);
                }
                
                if (header.ColorICT)
                {
                    PreProcessing.RGBfromICT(ref A, ref B, ref C, ref AA, ref BB, ref CC);
                }
                else
                {
                    PreProcessing.RGBfromYUV(ref A, ref B, ref C, ref AA, ref BB, ref CC);
                }

                PreProcessing.SetTile(ref res, ref AA, ref BB, ref CC, header.BlockSize, i);
            }            

            worker.Dispose();
            //MessageBox.Show("Complete");

            compressedImage.Image = res;
            compressedImage.Width = res.Width;
            compressedImage.Height = res.Height;
        }
       
        private void saveImageButton_Click(object sender, EventArgs e)
        {
            int size = (int)blockSize.Value;
            
            if (originalImage.Image == null) return;

            SaveFileDialog save = new SaveFileDialog();
            save.Filter = "Wavelet Images (*.wwt)|*.wwt";
            DialogResult res = save.ShowDialog();
            string filename = "";
            if (res == DialogResult.OK || res == DialogResult.Yes)
            {
                filename = save.FileName;
            }
            else
            {
                return;
            }

            float[][] A = null;
            Allocator(ref A, size);
            float[][] B = null;
            Allocator(ref B, size);
            float[][] C = null;
            Allocator(ref C, size);

            float[][] AA = null;
            Allocator(ref AA, size);
            float[][] BB = null;
            Allocator(ref BB, size);
            float[][] CC = null;
            Allocator(ref CC, size);

            int QuantVal = (int)quantification.Value;
            int deep = (int)depth.Value;

            ImageHeader header = new ImageHeader();
            header.BlockSize = (ushort)size;
            header.ColorICT = ictColorMode.Checked;
            header.Deep = (ushort)deep;
            header.Height = (ushort)originalImage.Image.Height;
            header.Width = (ushort)originalImage.Image.Width;
            header.Offset = valuesOffset.Checked;
            header.Quantilization = (ushort)QuantVal;

            FileWorker worker = new FileWorker(filename, false);
            header.SaveHeader(worker);

            int rows;
            int cols;
            int all;
            PreProcessing.GetCountTiles(originalImage.Image, size, out rows, out cols, out all);
            for (int i = 0; i < all; i++)
            {
                PreProcessing.GetTile((Bitmap)originalImage.Image, size, i, ref AA, ref BB, ref CC);

                
                if (header.ColorICT)
                {
                    PreProcessing.ICT(ref AA, ref BB, ref CC, ref A, ref B, ref C);
                }
                else
                {
                    PreProcessing.YUV(ref AA, ref BB, ref CC, ref A, ref B, ref C);
                }

                if (header.Offset)
                {
                    PreProcessing.Offset(ref A, size, size, false);
                    PreProcessing.Offset(ref B, size, size, false);
                    PreProcessing.Offset(ref C, size, size, false);
                }
                

                for (int j = 0; j < deep; j++)
                {
                    ImagePacker.Transform(ref A, ref AA, size >> j);
                    ImagePacker.Transform(ref B, ref BB, size >> j);
                    ImagePacker.Transform(ref C, ref CC, size >> j);
                    PreProcessing.Move(ref AA, ref A, size >> j);
                    PreProcessing.Move(ref BB, ref B, size >> j);
                    PreProcessing.Move(ref CC, ref C, size >> j);
                }

                PreProcessing.Quantilization(ref A, size, size, QuantVal, true);
                PreProcessing.Quantilization(ref B, size, size, QuantVal, true);
                PreProcessing.Quantilization(ref C, size, size, QuantVal, true);

                PreProcessing.SavePackets(size, A, B, C, worker);

                
            }
            
            worker.Dispose();
            MessageBox.Show("Complete");
        }
    }
}
